home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Tools
/
less-252
/
charset.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-11
|
6KB
|
287 lines
/*
* Copyright (c) 1984,1985,1989,1994 Mark Nudelman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice in the documentation and/or other materials provided with
* the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Functions to define the character set
* and do things specific to the character set.
*/
#include "less.h"
#if HAVE_LOCALE
#include <locale.h>
#include <ctype.h>
#endif
/*
* Predefined character sets,
* selected by the LESSCHARSET environment variable.
*/
struct charset {
char *name;
char *desc;
} charsets[] = {
{ "ascii", "8bcccbcc18b95.b" },
{ "latin1", "8bcccbcc18b95.33b." },
{ "dos", "8bcccbcc12bc5b95.98b.b" },
{ "koi8-r", "8bcccbcc18b95.b128." },
{ NULL }
};
#define IS_BINARY_CHAR 01
#define IS_CONTROL_CHAR 02
static char chardef[256];
static char *binfmt = NULL;
public int binattr = AT_STANDOUT;
/*
* Define a charset, given a description string.
* The string consists of 256 letters,
* one for each character in the charset.
* If the string is shorter than 256 letters, missing letters
* are taken to be identical to the last one.
* A decimal number followed by a letter is taken to be a
* repetition of the letter.
*
* Each letter is one of:
* . normal character
* b binary character
* c control character
*/
static void
ichardef(s)
char *s;
{
register char *cp;
register int n;
register char v;
n = 0;
v = 0;
cp = chardef;
while (*s != '\0')
{
switch (*s++)
{
case '.':
v = 0;
break;
case 'c':
v = IS_CONTROL_CHAR;
break;
case 'b':
v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = (10 * n) + (s[-1] - '0');
continue;
default:
error("invalid chardef", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
do
{
if (cp >= chardef + sizeof(chardef))
{
error("chardef longer than 256", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
*cp++ = v;
} while (--n > 0);
n = 0;
}
while (cp < chardef + sizeof(chardef))
*cp++ = v;
}
/*
* Define a charset, given a charset name.
* The valid charset names are listed in the "charsets" array.
*/
static int
icharset(name)
register char *name;
{
register struct charset *p;
if (name == NULL || *name == '\0')
return (0);
for (p = charsets; p->name != NULL; p++)
{
if (strcmp(name, p->name) == 0)
{
ichardef(p->desc);
return (1);
}
}
error("invalid charset name", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
#if HAVE_LOCALE
/*
* Define a charset, given a locale name.
*/
static void
ilocale()
{
register int c;
setlocale(LC_CTYPE, "");
for (c = 0; c < sizeof(chardef); c++)
{
if (isprint(c))
chardef[c] = 0;
else if (iscntrl(c))
chardef[c] = IS_CONTROL_CHAR;
else
chardef[c] = IS_BINARY_CHAR|IS_CONTROL_CHAR;
}
}
#endif
/*
* Define the printing format for control chars.
*/
public void
setbinfmt(s)
char *s;
{
if (s == NULL || *s == '\0')
s = "*s<%X>";
/*
* Select the attributes if it starts with "*".
*/
if (*s == '*')
{
switch (s[1])
{
case 'd': binattr = AT_BOLD; break;
case 'k': binattr = AT_BLINK; break;
case 's': binattr = AT_STANDOUT; break;
case 'u': binattr = AT_UNDERLINE; break;
default: binattr = AT_NORMAL; break;
}
s += 2;
}
binfmt = s;
}
/*
* Initialize charset data structures.
*/
public void
init_charset()
{
register char *s;
s = getenv("LESSBINFMT");
setbinfmt(s);
/*
* See if environment variable LESSCHARSET is defined.
*/
s = getenv("LESSCHARSET");
if (icharset(s))
return;
/*
* LESSCHARSET is not defined: try LESSCHARDEF.
*/
s = getenv("LESSCHARDEF");
if (s != NULL && *s != '\0')
{
ichardef(s);
return;
}
#if HAVE_LOCALE
/*
* Use setlocale.
*/
ilocale();
#else
/*
* Default to "ascii".
*/
(void) icharset("ascii");
#endif
}
/*
* Is a given character a "binary" character?
*/
public int
binary_char(c)
int c;
{
c &= 0377;
return (chardef[c] & IS_BINARY_CHAR);
}
/*
* Is a given character a "control" character?
*/
public int
control_char(c)
int c;
{
c &= 0377;
return (chardef[c] & IS_CONTROL_CHAR);
}
/*
* Return the printable form of a character.
* For example, in the "ascii" charset '\3' is printed as "^C".
*/
public char *
prchar(c)
int c;
{
static char buf[8];
c &= 0377;
if (!control_char(c))
sprintf(buf, "%c", c);
else if (c == ESC)
sprintf(buf, "ESC");
else if (!control_char(c ^ 0100))
sprintf(buf, "^%c", c ^ 0100);
else
sprintf(buf, binfmt, c);
return (buf);
}